package com.saas.ability.core.base.util;

import java.awt.geom.Point2D;
import java.util.List;

/**
 * 
* @ClassName: MapUtils 
* @Description: 判断地图是否在配送范围内
*
 */
public class MapUtils {

	/**
     * 计算两个坐标点之间的距离(返回千米)
     * @param lngA
     * @param latA
     * @param lngB
     * @param latB
     * @return
     */
    public static double calcDistance(double lngA,double latA,double lngB,double latB) {
        long earthR = 6378138;
        double x = Math.cos(latA * Math.PI / 180.) * Math.cos(latB * Math.PI / 180.) * Math.cos((lngA - lngB) * Math.PI / 180);
        double y = Math.sin(latA * Math.PI / 180.) * Math.sin(latB * Math.PI / 180.);
        double s = x + y;
        if (s > 1) s = 1;
        if (s < -1) s = -1;
        double alpha = Math.acos(s);
        double distance = alpha * earthR;
        if(distance > 0){
            distance = distance / 1000;
        }
        return distance;
    }


	/**
	 * 判断点是否在多边形内，如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
	 * @param point 检测点
	 * @param pts   多边形的顶点
	 * @return      点在多边形内返回true,否则返回false
	 */
	public static boolean IsPtInPoly(Point2D.Double point, List<Point2D.Double> pts){

		int N = pts.size();
		boolean boundOrVertex = true; //如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
		int intersectCount = 0;//cross points count of x
		double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
		Point2D.Double p1, p2;//neighbour bound vertices
		Point2D.Double p = point; //当前点

		p1 = pts.get(0);//left vertex
		for(int i = 1; i <= N; ++i){//check all rays
			if(p.equals(p1)){
				return boundOrVertex;//p is an vertex
			}

			p2 = pts.get(i % N);//right vertex
			if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){//ray is outside of our interests
				p1 = p2;
				continue;//next ray left point
			}

			if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){//ray is crossing over by the algorithm (common part of)
				if(p.y <= Math.max(p1.y, p2.y)){//x is before of ray
					if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){//overlies on a horizontal ray
						return boundOrVertex;
					}

					if(p1.y == p2.y){//ray is vertical
						if(p1.y == p.y){//overlies on a vertical ray
							return boundOrVertex;
						}else{//before ray
							++intersectCount;
						}
					}else{//cross point on the left side
						double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;//cross point of y
						if(Math.abs(p.y - xinters) < precision){//overlies on a ray
							return boundOrVertex;
						}

						if(p.y < xinters){//before ray
							++intersectCount;
						}
					}
				}
			}else{//special case when ray is crossing through the vertex
				if(p.x == p2.x && p.y <= p2.y){//p crossing over p2
					Point2D.Double p3 = pts.get((i+1) % N); //next vertex
					if(p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)){//p.x lies between p1.x & p3.x
						++intersectCount;
					}else{
						intersectCount += 2;
					}
				}
			}
			p1 = p2;//next ray left point
		}

		if(intersectCount % 2 == 0){//偶数在多边形外
			return false;
		} else { //奇数在多边形内
			return true;
		}
	}
}
